﻿namespace CloudNinja.Metering.Web.Authentication
{
    using System.Configuration;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Threading.Tasks;
    using System.Web.Http;
    using System.Web.Http.Dispatcher;

    using CloudNinja.Metering.Authentication;
    using CloudNinja.Metering.Data;

    public class HmacAuthHandler : DelegatingHandler
    {
        private readonly IApiKeyStore apiKeyStore;

        private readonly IHmacHelper hmacHelper;

        public HmacAuthHandler(IApiKeyStore apiKeyStore, IHmacHelper hmacHelper)
        {
            this.apiKeyStore = apiKeyStore;
            this.hmacHelper = hmacHelper;            
        }

        public void SetHttpConfiguration(HttpConfiguration config)
        {
            this.InnerHandler = new HttpControllerDispatcher(config);
        }

        protected bool IsAuthenticated(HttpRequestMessage request)
        {
            if (request.RequestUri.Segments.Any(x => x.Equals("$metadata")))
            {
                return true;
            }

            var authHeader = request.Headers.Authorization;
            if (authHeader.Scheme != HeaderNamesForHmac.AuthorizationScheme || string.IsNullOrEmpty(authHeader.Parameter))
            {
                return false;
            }

            var userId = this.hmacHelper.ValidateAuthenticationToken(request);

            return !string.IsNullOrEmpty(userId);

        }

        protected override async Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            System.Threading.CancellationToken cancellationToken)
        {
            if (this.IsAuthenticated(request))
            {
                return await base.SendAsync(request, cancellationToken);
            }

            var response = request.CreateErrorResponse(HttpStatusCode.Unauthorized, "Unathorized");
            response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue("Basic"));
            return response;
        }
    }
}
